package com.cskaoyan.javase.oop3._0abstract._0introduction;

/**
 * 以下猫狗继承案例，是一个非常基础的继承语法的代码。
 * 思考一下Animal类的继承体系，有什么问题吗？
 * 从以下两个角度分析：
 *      1.从代码角度上，有没有冗余代码？
 *      2.从设计角度上，在这个案例中，会存在一个动物对象吗？
 *
 * 结论:
 *      1.Animal类就是作为顶层抽象祖先类而存在的，不需要创建对象，它的作用就是被继承,于是干脆不要创建对象了。
 *      (创建对象就像干活,现在这个类不干活,只专注于被继承)
 *
 *      2.Animal类当中的shout方法不需要方法体，仅用于作为被继承和重写一个方法声明。
 *
 *
 * 于是:
 *      1.如何在类中声明抽象方法呢?
 *      抽象方法的语法:
 *      [修饰符列表] abstract 返回值类型 方法名(形参列表);
 *
 *      2.如何定义抽象类呢?
 *      语法:
 *      [修饰符列表] abstract class 类名{
 *          // 类体
 *      }
 *
 * 定义抽象类,抽象方法后,程序就不再报错了
 * 并且这时,抽象类无法创建对象,多态现象也能够正常发生,说明我们的改造成功了
 *
 * 总结:
 *      1.抽象方法和它的实现方法之间虽然是一个"实现(implement)"的关系
 *      但本质仍然是方法的重写(override)
 *
 *      2.抽象类,它是一种特殊的类,它仍然是一个类,但不能创建对象
 *
 * @since 11:33
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        Animal a;
        a = new Dog();
        a.shout();
        a = new Cat();
        a.shout();
        // 'Animal' is abstract; cannot be instantiated
        // Animal a2 = new Animal();
    }
}

abstract class Animal {
    /*
        报错:
        1.'{' or ';' expected
        2.Missing method body, or declare abstract 一个方法要么有方法体,要么就必须声明为抽象
        3.Abstract method in non-abstract class 抽象方法必须在抽象类中
          Class 'Animal' must either be declared abstract or implement abstract method 'shout()' in 'Animal'
          一个普通类是不允许出现抽象方法的,普通类中的方法必须是带有实现的普通方法
          总之,要想定义抽象方法,必须在抽象类中
     */
    public abstract void shout();
}

class Cat extends Animal {
    @Override
    public void shout() {
        System.out.println("猫叫");
    }
}

class Dog extends Animal {
    @Override
    public void shout() {
        System.out.println("狗叫");
    }
}